package Donnees;


import Metier.Objets.Commande;
import Metier.Objets.ModePaiement;
import Metier.Objets.Produit;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

public class DaoVente {
    
    private Connection connection;
    private Statement statement;
    private PreparedStatement preparedStatement;
    
    /**
     * Ajoute une vente en base de données avec ses paramètres
     * @param c  objet commande à ajouter
     * @throws SQLException 
     */
    public void ajouter(Commande c) throws SQLException{
        try{
            //Récupération de la connexion
            connection = ConnectionFactory.getConnection();
            
            //Déclaration de la requête pour créer la vente
            String query = "INSERT INTO VENTE (date, mode_paiement, prix_total)"
                    + " VALUES (?, ?, ?)";
            
            //Préparation de la requête
            preparedStatement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
            preparedStatement.setTimestamp(1, c.getDate());
            preparedStatement.setString(2, c.getModePaiement().toString());
            preparedStatement.setFloat(3, c.getPrixTotal());
            
            //Exécution de la requête
            preparedStatement.executeUpdate();
            int id_vente = -1;
            try (ResultSet generatedKeys = preparedStatement.getGeneratedKeys()) {
                if (generatedKeys.next()) {
                    id_vente = generatedKeys.getInt(1);
                }
                else {
                    throw new SQLException("Creating Commande failed, no ID obtained.");
                }
            }

            //Déclaration de la requête pour les lignes de la vente
            query = "INSERT INTO DETAILS_VENTE (VENTE_id, PRODUIT_id, quantite)"
                    + " VALUES (?, ?, ?)";
            
            for(Entry<Produit, Integer> entry : c.getProduitCommande().entrySet()){
                //Préparation de la requête
                preparedStatement = connection.prepareStatement(query);
                preparedStatement.setInt(1, id_vente);
                preparedStatement.setInt(2, entry.getKey().getId());
                preparedStatement.setInt(3, entry.getValue());

                //Exécution de la requête
                preparedStatement.executeUpdate();
            }
        }
        finally{
            DbUtil.close(preparedStatement);
            DbUtil.close(connection);
        }
    }
    
    /**
     * Supprime toute la commande renseignée
     * @param vente commande a supprimer
     * @throws SQLException 
     */
    public void supprimer(Commande vente) throws SQLException{
        try {
            String query;
            //on supprime d'abord les lignes
            query = "DELETE FROM DETAILS_VENTE where VENTE_id = " + vente.getId();
            connection = ConnectionFactory.getConnection();
            statement = connection.createStatement();
            statement.execute(query);
            //ensuite on supprime la commande
            query = "DELETE FROM VENTE where id = " + vente.getId();
            statement = connection.createStatement();
            statement.execute(query);
        } finally {
            DbUtil.close(statement);
            DbUtil.close(connection);
        }
    }
    
    /**
     * Récupère les ventes qui ont eu lieu à une date donnée
     * @param d  date pour laquelle on veut les ventes
     * @return la liste des ventes à la date spécifiée
     * @throws SQLException
     */
    public List<Commande> chercherVentesParDate(Date d) throws SQLException{
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String where = "WHERE date = '" + df.format(d) + "'";
        return chercherVente(where);
    }
    
    /**
     * Récupère toutes les ventes
     * @return la liste des ventes réalisées depuis la mise en place du logiciel
     * @throws SQLException
     */
    public List<Commande> chercherVentes() throws SQLException{
        return chercherVente("");
    }
    
    /**
     * Récupère une vente à partir de son id
     * @param id id de la vente concernée
     * @return la commande demandée
     * @throws SQLException
     */
    public Commande chercherVenteParId(int id) throws SQLException{
        String where = " WHERE id = " + id;
        return chercherVente(where).get(0);
    }
    
    /**
     * Méthode privée dee recherche de commande en fonction d'une clause where définie dans l'une des méthodes de recherche publiques
     * @param whereClause la clause spécifique
     * @return la liste des commandes correspondant à la clause
     * @throws SQLException 
     */
    private List<Commande> chercherVente(String whereClause) throws SQLException{
        List<Commande> listeCommandes = new ArrayList<>();
        try {
            Commande c;
            //initialisation de la liste des commandes
            ResultSet rs, rs_detail;
            String query = "SELECT * FROM VENTE " + whereClause;
            connection = ConnectionFactory.getConnection();
            statement = connection.createStatement();
            rs = statement.executeQuery(query);
            
            //préparation de la requête qui va servir pour chaque commande à récupérer ses différentes lignes
            query = "SELECT * FROM DETAILS_VENTE WHERE VENTE_id = ?";
            HashMap<Produit, Integer> quantites;
            DaoProduit daoProduit = new DaoProduit();
            while (rs.next()) {
                Timestamp date = rs.getTimestamp("date");
                preparedStatement = connection.prepareStatement(query);
                preparedStatement.setInt(1, rs.getInt("id"));
                rs_detail = preparedStatement.executeQuery();
                quantites = new HashMap<>();
                while(rs_detail.next()){
                    quantites.put(daoProduit.chercher(rs_detail.getInt("PRODUIT_id")), rs_detail.getInt("quantite"));
                }
                
                c = new Commande(rs.getInt("id"), ModePaiement.valueOf(rs.getString("mode_paiement")), date, quantites, rs.getFloat("prix_total"));
                listeCommandes.add(c);
            }
        } finally {
            DbUtil.close(statement);
            DbUtil.close(connection);
        }
        return listeCommandes;
    }
    
    /**
     * Modifie la commande renseignée en base de données.
     * @param commande commande à modifier
     * @throws SQLException 
     */
    public void modifier(Commande commande) throws SQLException{
        try{
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            
            //Récupération de la connexion
            connection = ConnectionFactory.getConnection();
            
            //Déclaration de la requête
            String query = "UPDATE VENTE SET date = ?, prix_total = ?"
                            + " where id = ?";
            
            //Préparation de la requête
            preparedStatement = connection.prepareStatement(query);
            preparedStatement.setTimestamp(1, commande.getDate());
            preparedStatement.setFloat(2, commande.getPrixTotal());
            preparedStatement.setInt(3, commande.getId());
            
            //Exécution de la requête
            preparedStatement.executeUpdate();
            
            
        }
        finally{
            DbUtil.close(preparedStatement);
            DbUtil.close(connection);
        }
    }
}
